package com.dycong.common.IO.socket.SSL;

import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Created by dycong on 2017/3/31.
 */
public class MyX509TrustManager implements X509TrustManager {
    /* 使用自定义的 MyTrustManager 产生信任库
    TrustManager[] tms=new TrustManager[]{new SelfX509TrustManager()};
*/

    // 相关的 jks 文件及其密码定义
    private final static String TRUST_STORE = "D:/test_client_trust.jks";
    private final static String TRUST_STORE_PASSWORD = "Testpassw0rd";
    X509TrustManager xtm;

    public MyX509TrustManager() throws Exception {
        // 载入 jks 文件
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream(TRUST_STORE), TRUST_STORE_PASSWORD.toCharArray());
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
        tmf.init(ks);
        TrustManager[] tms = tmf.getTrustManagers();
        // 筛选出 X509 格式的信任证书
        for (int i = 0; i < tms.length; i++) {
            if (tms[i] instanceof X509TrustManager) {
                xtm = (X509TrustManager) tms[i];
                return;
            }
        }
    }

    public void checkClientTrusted(X509Certificate[] var1, String var2) throws CertificateException {

    }

    public void checkServerTrusted(X509Certificate[] var1, String var2) throws CertificateException {
        try {
            xtm.checkServerTrusted(var1, var2);
        } catch (CertificateException excep) {
            System.out.println(excep.getMessage());
            throw excep;
        }
    }

    // 获取可接受的发行者
    public X509Certificate[] getAcceptedIssuers() {
        return xtm.getAcceptedIssuers();
//       return null;
    }
    /**
     * X509TrustManager 接口扩展了 TrustManager 接口，使用 TrustManager 接口，我们已经可以在程序中自定义信任库了，但如果对方的证书不在信任库中，则通信会直接宣告失败。
     *如果希望能自定义信任库的一些行为 ( 例如：检验对方证书，针对异常做一些处理 )，我们可以使用 X509TrustManager 接口，实现自己的方法。
     *
     * 1. 当服务端代码 setNeedClientAuth(False) 时，客户端的 MyTrustManager 实现了 X509TrustManager 后，如果 checkServerTrusted() 方法的实现为空，
     * 则无论服务端使用什么证书，客户端都会默认接受；如果要对服务端证书进行检查，还需要像清单 5 中的代码片段那样，捕捉异常并处理。
     *
     *2.getAcceptedIssuers() 方法通常不需要具体实现，但是当服务端要求检验客户端身份，也即 setNeedClientAuth(True) 时，
     *服务端需也需要具体实现 X509TrustManager，且 getAcceptedIssuers() 方法要如清单 5 中注释部分代码那样实现。
     */

}
